
package com.hlkj.pay.gateway.ad.impl;
/*
 * Hlpay-Plus aggregate payment system.
 * Copyright (c) 2024-2025 Hlpay Team Copyright has the right of final interpretation.
 */

import java.io.IOException;
import java.util.HashMap;
import java.util.Map;
import java.util.UUID;

import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Service;

import com.alibaba.fastjson.JSONObject;
import com.hlkj.framework.common.util.json.JsonUtils;
import com.hlkj.framework.http.template.OkHttpTemplate;
import com.hlkj.pay.app.ad.constant.AdConstant;
import com.hlkj.pay.app.ad.impl.AdPayOrderHandlerParams;
import com.hlkj.pay.dto.ad.gateway.Tuia;
import com.hlkj.pay.dto.ad.query.HlPayOrderQueryResultDto;
import com.hlkj.pay.dto.ad.query.HlRefundOrderQueryResultDto;
import com.hlkj.pay.dto.ad.result.HlPayDataCommonResultDto;
import com.hlkj.pay.dto.ad.result.HlPayDataResultDto;
import com.hlkj.pay.dto.ad.result.HlRefundDataResultDto;
import com.hlkj.pay.enums.PayEnums;
import com.hlkj.pay.gateway.ad.IAdOrderGateway;
import com.hlkj.pay.infrastructure.model.ad.AdInfoConfigDO;
import com.hlkj.pay.infrastructure.model.ad.AdInfoDO;
import com.hlkj.pay.infrastructure.model.ad.AdPayOrderDO;
import com.hlkj.pay.infrastructure.model.ad.AdRefundOrderDO;
import com.hlkj.pay.infrastructure.model.pay.PayChannelRequestDO;
import com.hlkj.pay.service.pay.IPayChannelService;
import com.hlkj.pay.util.MerchantUtils;

import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import net.dreamlu.mica.core.utils.BeanUtil;
import net.dreamlu.mica.core.utils.StringUtil;
import okhttp3.*;

/**
 * @author HlpayTeam
 * @date 2024/11/04 8:58
 */
@Slf4j
@Service
@RequiredArgsConstructor
public class AdOrderGatewayImpl implements IAdOrderGateway {

    private final AdPayOrderHandlerParams adPayOrderHandlerParams;

    private final IPayChannelService payChannelService;

    private final OkHttpTemplate okHttpTemplate;

    @Value("${hlkj.barrier:false}")
    private boolean barrier;

    @Override
    public HlPayDataResultDto submitPayOrder(AdPayOrderDO payOrderDO, AdInfoDO adInfoDO, AdInfoConfigDO adInfoConfigDO) throws Exception {
        if (barrier) {
            HlPayDataResultDto hlPayDataResultDto = new HlPayDataResultDto();
            hlPayDataResultDto.setCode(1);
            hlPayDataResultDto.setMsg("请求成功");
            hlPayDataResultDto.setSign_type("RSA2");
            hlPayDataResultDto.setIns_id(adInfoConfigDO.getSn());
            hlPayDataResultDto.setApp_id(adInfoConfigDO.getAppId());
            HlPayDataResultDto.DataBean dataBean = new HlPayDataResultDto.DataBean();
            dataBean.setIns_id(adInfoConfigDO.getSn());
            dataBean.setApp_id(adInfoConfigDO.getAppId());
            dataBean.setMch_order_no(payOrderDO.getMchOrderNo());
            dataBean.setPay_order_id(payOrderDO.getMchOrderNo());
            dataBean.setIn_code("alipay");
            dataBean.setWay_code("alipay");
            dataBean.setAmount(payOrderDO.getAmount().doubleValue());
            dataBean.setPay_data_type("pay_url");
            dataBean.setPay_info("https://qr.alipay.com/bax04541w25lmciec7tw0073");
            hlPayDataResultDto.setData(dataBean);
            hlPayDataResultDto.setSign(null);
            return hlPayDataResultDto;
        }
        Map<String, Object> params = adPayOrderHandlerParams.submitPayParams(payOrderDO, adInfoDO, adInfoConfigDO);
        // 发起post请求
        log.info("发起支付 请求参数 params:{}", JSONObject.toJSONString(params));
        PayChannelRequestDO payChannelRequestDO = new PayChannelRequestDO();
        payChannelRequestDO.setSn(payOrderDO.getSn());
        payChannelRequestDO.setRelationId(payOrderDO.getMchOrderNo());
        payChannelRequestDO.setRequestUrl("POST " + AdConstant.SUBMIT_PAY_ORDER_URL);
        payChannelRequestDO.setRequestParams(JsonUtils.toJsonString(params));
        long now = System.currentTimeMillis();
        String postJson = okHttpTemplate.post(AdConstant.SUBMIT_PAY_ORDER_URL, JSONObject.toJSONString(params), null);
        long end = System.currentTimeMillis();
        payChannelRequestDO.setRequestTime((end - now));
        log.info("发起支付 返回参数 postJson:{}", JsonUtils.toJsonString(postJson));
        payChannelRequestDO.setResponse(postJson);
        payChannelService.saveRequest(payChannelRequestDO, PayEnums.CHANNEL_REQUEST_TYPE.AD_PAY_ORDER);
        if (StringUtil.hasText(postJson)) {
            try {
                return JsonUtils.parseObject(postJson, HlPayDataResultDto.class);
            }
            catch (Exception e) {
                HlPayDataCommonResultDto hlPayDataCommonResultDto = JsonUtils.parseObject(postJson, HlPayDataCommonResultDto.class);
                hlPayDataCommonResultDto.setData(null);
                return BeanUtil.copyProperties(hlPayDataCommonResultDto, HlPayDataResultDto.class);
            }
        }
        return null;
    }

    @Override
    public HlRefundDataResultDto submitRefundOrder(AdRefundOrderDO adRefundOrderDO, AdInfoConfigDO adInfoConfigDO) throws Exception {
        if (barrier) {
            HlRefundDataResultDto hlRefundDataResultDto = new HlRefundDataResultDto();
            hlRefundDataResultDto.setCode(1);
            hlRefundDataResultDto.setMsg("请求成功");
            hlRefundDataResultDto.setSign_type("RSA2");
            hlRefundDataResultDto.setIns_id(adInfoConfigDO.getSn());
            hlRefundDataResultDto.setApp_id(adInfoConfigDO.getAppId());
            HlRefundDataResultDto.DataBean refundDataBean = new HlRefundDataResultDto.DataBean();
            refundDataBean.setIns_id(adInfoConfigDO.getSn());
            refundDataBean.setApp_id(adInfoConfigDO.getAppId());
            refundDataBean.setMch_order_no(adRefundOrderDO.getMchOrderNo());
            refundDataBean.setPay_order_id(adRefundOrderDO.getRefundOrderNo());
            refundDataBean.setMch_refund_no(adRefundOrderDO.getRefundOrderNo());
            refundDataBean.setRefund_amount(adRefundOrderDO.getRefundAmount().doubleValue());
            refundDataBean.setRefund_reason(adRefundOrderDO.getRefundReason());
            refundDataBean.setRefund_order_id(adRefundOrderDO.getRefundOrderNo());
            refundDataBean.setState(2);
            refundDataBean.setErr_msg("");
            hlRefundDataResultDto.setData(refundDataBean);
            hlRefundDataResultDto.setSign("");
            return hlRefundDataResultDto;
        }
        Map<String, Object> params = adPayOrderHandlerParams.submitRefundParams(adRefundOrderDO, adInfoConfigDO);
        log.info("ad 订单发起退款 请求参数:{}", JSONObject.toJSONString(params));
        PayChannelRequestDO payChannelRequestDO = new PayChannelRequestDO();
        payChannelRequestDO.setSn(adRefundOrderDO.getSn());
        payChannelRequestDO.setRelationId(adRefundOrderDO.getRefundOrderNo());
        payChannelRequestDO.setRequestUrl("POST " + AdConstant.REFUND_ORDER_URL);
        payChannelRequestDO.setRequestParams(JsonUtils.toJsonString(params));
        long now = System.currentTimeMillis();
        // 发起post请求
        String postJson = okHttpTemplate.post(AdConstant.REFUND_ORDER_URL, JSONObject.toJSONString(params), null);
        payChannelRequestDO.setResponse(postJson);
        payChannelRequestDO.setRequestTime((System.currentTimeMillis() - now));
        log.info("ad 订单发起退款 返回参数:{}", postJson);
        if (!barrier) {
            payChannelService.saveRequest(payChannelRequestDO, PayEnums.CHANNEL_REQUEST_TYPE.AD_PAY_ORDER);
        }
        if (StringUtil.hasText(postJson)) {
            try {
                return JsonUtils.parseObject(postJson, HlRefundDataResultDto.class);
            }
            catch (Exception e) {
                HlPayDataCommonResultDto hlPayDataCommonResultDto = JsonUtils.parseObject(postJson, HlPayDataCommonResultDto.class);
                hlPayDataCommonResultDto.setData(null);
                return BeanUtil.copyProperties(hlPayDataCommonResultDto, HlRefundDataResultDto.class);
            }

        }
        return null;
    }

    @Override
    public HlRefundOrderQueryResultDto queryRefundOrder(AdRefundOrderDO adRefundOrderDO, AdInfoConfigDO adInfoConfigDO) throws Exception {

        if (barrier) {
            HlRefundOrderQueryResultDto hlRefundOrderQueryResultDto = new HlRefundOrderQueryResultDto();
            hlRefundOrderQueryResultDto.setCode(1);
            hlRefundOrderQueryResultDto.setMsg("请求成功");
            hlRefundOrderQueryResultDto.setSign_type("RSA2");
            hlRefundOrderQueryResultDto.setIns_id(adInfoConfigDO.getSn());
            hlRefundOrderQueryResultDto.setApp_id(adInfoConfigDO.getAppId());
            HlRefundOrderQueryResultDto.RefundOrderData refundDataDtoData = new HlRefundOrderQueryResultDto.RefundOrderData();
            refundDataDtoData.setIns_id(adInfoConfigDO.getSn());
            refundDataDtoData.setApp_id(adInfoConfigDO.getAppId());
            refundDataDtoData.setMch_order_no(adRefundOrderDO.getMchOrderNo());
            // refundDataDtoData.setPay_order_id();
            refundDataDtoData.setMch_refund_no(adRefundOrderDO.getRefundOrderNo());
            refundDataDtoData.setRefund_amount(adRefundOrderDO.getRefundAmount().doubleValue());
            refundDataDtoData.setRefund_reason(adRefundOrderDO.getRefundReason());
            refundDataDtoData.setRefund_order_id(adRefundOrderDO.getRefundOrderNo());
            refundDataDtoData.setState("3");
            hlRefundOrderQueryResultDto.setData(refundDataDtoData);
            hlRefundOrderQueryResultDto.setSign("");
            return hlRefundOrderQueryResultDto;
        }
        Map<String, Object> params = adPayOrderHandlerParams.queryRefundParams(adRefundOrderDO.getRefundOrderNo(), adInfoConfigDO);
        // 发起post请求
        log.info("ad 查询退款结果 请求参数:{}", JSONObject.toJSONString(params));
        String postJson = okHttpTemplate.post(AdConstant.QUERY_REFUND_ORDER_URL, JSONObject.toJSONString(params), null);
        log.info("ad 查询退款结果 返回参数:{}", postJson);
        if (StringUtil.hasText(postJson)) {
            try {
                return JsonUtils.parseObject(postJson, HlRefundOrderQueryResultDto.class);
            }
            catch (Exception e) {
                HlPayDataCommonResultDto hlPayDataCommonResultDto = JsonUtils.parseObject(postJson, HlPayDataCommonResultDto.class);
                hlPayDataCommonResultDto.setData(null);
                return BeanUtil.copyProperties(hlPayDataCommonResultDto, HlRefundOrderQueryResultDto.class);
            }
        }
        return null;
    }

    @Override
    public HlPayOrderQueryResultDto queryOrder(AdPayOrderDO payOrderDO, AdInfoConfigDO adInfoConfigDO) throws Exception {
        if (barrier) {
            HlPayOrderQueryResultDto hlPayOrderQueryResultDto = new HlPayOrderQueryResultDto();
            hlPayOrderQueryResultDto.setCode(1);
            hlPayOrderQueryResultDto.setMsg("请求成功");
            hlPayOrderQueryResultDto.setSign_type("RSA2");
            hlPayOrderQueryResultDto.setIns_id(adInfoConfigDO.getSn());
            hlPayOrderQueryResultDto.setApp_id(adInfoConfigDO.getAppId());
            HlPayOrderQueryResultDto.PayOrderQueryData payOrderQueryData = new HlPayOrderQueryResultDto.PayOrderQueryData();
            payOrderQueryData.setIns_id(adInfoConfigDO.getSn());
            payOrderQueryData.setApp_id(adInfoConfigDO.getAppId());
            payOrderQueryData.setMch_order_no(payOrderDO.getMchOrderNo());
            payOrderQueryData.setPay_order_id(payOrderDO.getMchOrderNo());
            payOrderQueryData.setIns_order_sn(payOrderDO.getMchOrderNo());
            payOrderQueryData.setChannel_order_sn(payOrderDO.getMchOrderNo());
            payOrderQueryData.setAmount(MerchantUtils.bigDecimalToString(payOrderDO.getAmount()));
            payOrderQueryData.setMch_channel_id("");
            payOrderQueryData.setIn_code("");
            payOrderQueryData.setWay_code("");
            payOrderQueryData.setSp_sn("");
            payOrderQueryData.setWay_scene("");
            payOrderQueryData.setWay_type("");
            payOrderQueryData.setCom_fee_amount("");
            payOrderQueryData.setCom_fee_rate("");
            payOrderQueryData.setChanne_fee_amount("");
            payOrderQueryData.setChanne_fee_rate("");
            payOrderQueryData.setSettlement_amt("");
            payOrderQueryData.setSubject(payOrderDO.getSubject());
            payOrderQueryData.setBody(payOrderDO.getDescription());
            payOrderQueryData.setSuccess_time(String.valueOf(System.currentTimeMillis() / 1000));
            payOrderQueryData.setState("3");
            hlPayOrderQueryResultDto.setData(payOrderQueryData);
            hlPayOrderQueryResultDto.setSign("");
            return hlPayOrderQueryResultDto;
        }
        Map<String, Object> params = adPayOrderHandlerParams.queryPayParams(payOrderDO.getMchOrderNo(), adInfoConfigDO);
        // 发起post请求
        String postJson = okHttpTemplate.post(AdConstant.QUERY_PAY_ORDER_URL, JSONObject.toJSONString(params), null);
        if (StringUtil.hasText(postJson)) {
            try {
                return JsonUtils.parseObject(postJson, HlPayOrderQueryResultDto.class);
            }
            catch (Exception e) {
                HlPayDataCommonResultDto hlPayDataCommonResultDto = JsonUtils.parseObject(postJson, HlPayDataCommonResultDto.class);
                hlPayDataCommonResultDto.setData(null);
                return BeanUtil.copyProperties(hlPayDataCommonResultDto, HlPayOrderQueryResultDto.class);
            }

        }
        return null;
    }

    @Override
    public Tuia syncCallBack(AdInfoConfigDO adInfoConfigDO, Long adMediaId, String aOId) throws Exception {
        if (barrier) {
            Tuia tuia = new Tuia();
            tuia.setRedesc("成功 入参外网ip为空； 入参客户端ua为空； 入参客户端设备device为空；");
            tuia.setRecord("0000000");
            tuia.setA_oId(UUID.randomUUID().toString());
            return tuia;
        }
        if (adMediaId == 1) {
            return syncTuia(adInfoConfigDO, aOId);
        }
        else if (adMediaId == 2) {
            return syncBianXianMao(adInfoConfigDO, aOId);
        }
        return null;
    }

    /**
     * 推啊回调
     * 
     * @param adInfoConfigDO
     * @param aOId
     * @return
     * @throws Exception
     */
    public Tuia syncTuia(AdInfoConfigDO adInfoConfigDO, String aOId) throws Exception {
        String postJson = null;
        // 创建 OkHttpClient 实例
        OkHttpClient client = new OkHttpClient();
        // 创建表单构建器
        MultipartBody.Builder builder = new MultipartBody.Builder().setType(MultipartBody.FORM).addFormDataPart("a_oId", aOId) // 添加表单字段
                .addFormDataPart("advertKey", adInfoConfigDO.getMediaPrivateKey()).addFormDataPart("subType", "3");
        // 构建请求体
        RequestBody requestBody = builder.build();
        // 创建请求
        Request request = new Request.Builder().url(AdConstant.ACTIVITY_CALL_URL) // 替换为你的 API URL
                .post(requestBody) // 使用 POST 方法
                .build();
        // 发送请求并获取响应
        try (Response response = client.newCall(request).execute()) {
            if (!response.isSuccessful()) {
                throw new IOException("Unexpected code " + response);
            }
            // 处理响应
            postJson = response.body().string();
        }
        if (StringUtil.hasText(postJson)) {
            return JsonUtils.parseObject(postJson, Tuia.class);
        }
        return null;
    }

    /**
     * 变现猫回调
     * 
     * @param adInfoConfigDO
     * @param aOId
     * @return
     * @throws Exception
     */
    public Tuia syncBianXianMao(AdInfoConfigDO adInfoConfigDO, String aOId) throws Exception {
        String postJson = null;
        // 创建 OkHttpClient 实例
        OkHttpClient client = new OkHttpClient();
        // 创建表单构建器
        MultipartBody.Builder builder = new MultipartBody.Builder().setType(MultipartBody.FORM).addFormDataPart("a_oId", aOId) // 添加表单字段
                .addFormDataPart("advertKey", adInfoConfigDO.getMediaPrivateKey()).addFormDataPart("subType", "3");
        // 构建请求体
        RequestBody requestBody = builder.build();
        // 创建请求
        Request request = new Request.Builder().url(AdConstant.ACTIVITY_CALL_URL) // 替换为你的 API URL
                .post(requestBody) // 使用 POST 方法
                .build();
        // 发送请求并获取响应
        try (Response response = client.newCall(request).execute()) {
            if (!response.isSuccessful()) {
                throw new IOException("Unexpected code " + response);
            }
            // 处理响应
            postJson = response.body().string();
        }
        if (StringUtil.hasText(postJson)) {
            return JsonUtils.parseObject(postJson, Tuia.class);
        }
        StringBuilder sb = new StringBuilder();
        sb.append("https://openlog.bianxianmao.com/inads/s.gif");
        sb.append("?");
        sb.append("mt=8");
        sb.append("&");
        sb.append("bxmid=");
        sb.append(aOId);
        sb.append("&");
        sb.append("conversion_type=5");
        okHttpTemplate.get(sb.toString(), new HashMap<>());
        Tuia tuia = new Tuia();
        tuia.setRecord("0000000");
        return tuia;
    }
}
